#main.py

import sys
import tkinter as tk
import matplotlib.pyplot as plt
from screeninfo import get_monitors # 用于获取屏幕真实尺寸，便于窗口定位
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from device import draw_static_elements, draw_dynamic_elements, update_dynamic_elements   # 自定义模块，用于生成装置示意图
from mask import generate_mask   # 自定义模块，用于生成掩膜版图
from result import generate_result  # 自定义模块，用于生成计算结果图
from help import HelpWindow  # 自定义类，用于渲染帮助文本


# 图像更新fig函数母版，用于更新掩膜版图和计算结果图区域的图像
def update_figure(generate_function, *args, fig_size=(9, 3), canvas=None):
    plt.close('all')  # 关闭当前图形，以免内存泄漏

    # 调用生成图形的函数
    fig = generate_function(*args)
    fig.set_size_inches(*fig_size)

    # 更新图形
    canvas.figure = fig
    canvas.draw()


# 设置掩膜版图的更新函数
def update_mask():
    b_val = b_var.get()
    update_figure(generate_mask, b_val, fig_size=(9, 3), canvas=mask_canvas)


# 设置计算结果图的更新函数
def update_result(*args):
    sin_val = sin_slider.get()
    n_val = n_slider.get()
    wavelength_val = wavelength_slider.get()
    m_val = m_var.get()
    b_val = b_var.get()
    op_status_val = op_status_var.get()

    update_figure(generate_result, sin_val, n_val, wavelength_val, m_val, b_val, op_status_val, fig_size=(9, 3), canvas=result_canvas)


# 设置相干按钮的响应函数
def toggle_coherence():
    m_var.set(1 - m_var.get())
    update_result()
    m_button.config(text="非相干" if m_var.get() == 1 else "相干")


# 设置启用OPC按钮的响应函数
def toggle_opc():
    b_var.set(1 - b_var.get())
    
    # 如果 b=1，锁定滑块的值
    if b_var.get() == 1:
        n_slider.set(1.0)
        sin_slider.set(0.9)
        wavelength_slider.set(2.3)
        n_slider.config(state=tk.DISABLED)
        sin_slider.config(state=tk.DISABLED)
        wavelength_slider.config(state=tk.DISABLED)

        # 显示锁图标
        sin_lock_label.config(image=lock_icon)
        n_lock_label.config(image=lock_icon)
        wavelength_lock_label.config(image=lock_icon)
    else:
        # 如果 b=0，解锁滑块

        n_slider.config(state=tk.NORMAL)
        sin_slider.config(state=tk.NORMAL)
        wavelength_slider.config(state=tk.NORMAL)

        # 隐藏锁图标
        sin_lock_label.config(image="")
        n_lock_label.config(image="")
        wavelength_lock_label.config(image="")
    
    update_mask()
    update_result()
    b_button.config(text="启用" if b_var.get() == 1 else "不启用")


# 设置光强/边界按钮的响应函数
def toggle_display():
    op_status_var.set(1 - op_status_var.get())
    update_result()
    op_status_button.config(text="边界" if op_status_var.get() == 1 else "光强")


# 设置装置示意图和计算结果图的联合更新函数，用于sin和n滑块的响应函数
def update_device_and_result(*args):
    sin_value = sin_slider.get()
    n_value = n_slider.get()
    update_dynamic_elements(device_canvas, sin_value, n_value)
    update_result()


# 绘制坐标系网格的功能函数
def draw_grid(root, line_distance):
    basic_canvas = tk.Canvas(root, width=window_width, height=window_height) #创建基本画布
    basic_canvas.pack()

    # 获取画布的宽度和高度
    width = basic_canvas.winfo_reqwidth()
    height = basic_canvas.winfo_reqheight()
    # 绘制垂直线和垂直坐标
    for i in range(0, width, line_distance):
        basic_canvas.create_line(i, 0, i, height, fill="#d3d3d3")
        basic_canvas.create_text(i, 0, anchor='n', text=str(i))
    # 绘制水平线和水平坐标
    for i in range(0, height, line_distance):
        basic_canvas.create_line(0, i, width, i, fill="#d3d3d3")
        basic_canvas.create_text(width / 2, i, anchor='w', text=str(i))

# 设置帮助按钮的响应函数
def show_help():
    help_window = HelpWindow()
    help_window.run()


# 设置关闭窗口时的处理函数
def on_closing():
    root.destroy()
    sys.exit(0)



# 创建主窗口
root = tk.Tk()
root.title("光刻")

#自定义窗口大小和位置
window_width = 1800
window_height = 1200

# 获取用户屏幕尺寸，计算屏幕的中心位置
monitor = get_monitors()[0]
screen_width = monitor.width
screen_height = monitor.height
position_top = int((screen_height - window_height) / 2)
position_right = int((screen_width - window_width) / 2)

# 设置窗口的位置
root.geometry(f"{window_width}x{window_height}+{position_right}+{position_top}")


# 绘制基本坐标系，方便调试代码时定位坐标
#draw_grid(root, 50)


# 创建装置示意图容器
device_frame = tk.Frame(root, width=600, height=600)
device_frame.place(x=150, y=0)
device_canvas = tk.Canvas(device_frame, width=800, height=800)
device_canvas.place(x=0, y=0)


# 创建掩膜版图容器
mask_frame = tk.Frame(root, width=900, height=300)
mask_frame.place(x=0, y=600)

mask_fig = plt.Figure(figsize=(9, 3))
mask_ax = mask_fig.add_subplot(111)
mask_canvas = FigureCanvasTkAgg(mask_fig, master=mask_frame)
mask_canvas_widget = mask_canvas.get_tk_widget()
mask_canvas_widget.place(relwidth=1, relheight=1)


# 创建计算结果图容器
result_frame = tk.Frame(root, width=900, height=300)
result_frame.place(x=0, y=900)

result_fig = plt.Figure(figsize=(9, 3))
result_ax = result_fig.add_subplot(111)
result_canvas = FigureCanvasTkAgg(result_fig, master=result_frame)
result_canvas_widget = result_canvas.get_tk_widget()
result_canvas_widget.place(relwidth=1, relheight=1)


# 创建右侧控制区
control_frame = tk.Frame(root, width=650, height=1100)
control_frame.place(x=1050, y=100)


# 布局标签和滑块
sin_label = tk.Label(control_frame, text="sin θ", font=('Times New Roman', 18, 'italic'))  
sin_label.place(x=10, y=25)
sin_slider = tk.Scale(control_frame, from_=0.1, to=0.9, resolution=0.1, orient=tk.HORIZONTAL, command=update_device_and_result, length=300) 
sin_slider.place(x=100, y=10)
sin_range_label = tk.Label(control_frame, text="(0.1 to 0.9)", font=('Times New Roman', 18))  
sin_range_label.place(x=400, y=25)

n_label = tk.Label(control_frame, text="n", font=('Times New Roman', 18, 'italic'))
n_label.place(x=20, y=175)
n_slider = tk.Scale(control_frame, from_=1.0, to=1.7, resolution=0.1, orient=tk.HORIZONTAL, command=update_device_and_result, length=300)
n_slider.place(x=100, y=160)
n_range_label = tk.Label(control_frame, text="(1.0 to 1.7)", font=('Times New Roman', 18))
n_range_label.place(x=400, y=175)

wavelength_label = tk.Label(control_frame, text="λ/μm",font=('Times New Roman', 18, 'italic'))
wavelength_label.place(x=10, y=325)
wavelength_slider = tk.Scale(control_frame, from_=1.0, to=8.0, resolution=0.1, orient=tk.HORIZONTAL, command=update_result, length=300)
wavelength_slider.place(x=100, y=310)
wavelength_range_label = tk.Label(control_frame, text="(1.0 to 8.0)", font=('Times New Roman', 18))
wavelength_range_label.place(x=400, y=325)

# 加载锁图标，在相应的Labe左侧显示锁
lock_icon = tk.PhotoImage(file="lock_icon.png")  
lock_icon = lock_icon.subsample(16)  # 缩小为原来的1/16

sin_lock_label = tk.Label(control_frame, image="")
sin_lock_label.place(x=540, y=23)

n_lock_label = tk.Label(control_frame, image="")
n_lock_label.place(x=540, y=171)

wavelength_lock_label = tk.Label(control_frame, image="")
wavelength_lock_label.place(x=540, y=319)


# 设置Button字体大小
font_size = 20
button_font = ('SimSun', font_size)


# 添加 IntVar 和 Button
m_var = tk.IntVar()
m_button = tk.Button(control_frame, text="相干", command=toggle_coherence, font=button_font, width=8)
m_button.place(x=350, y=475)
m_lable = tk.Label(control_frame, text="光源相干性：", font=('SimSun', 20, 'bold'))
m_lable.place(x=80, y=487)

op_status_var = tk.IntVar()
op_status_button = tk.Button(control_frame, text="光强", command=toggle_display, font=button_font, width=8)
op_status_button.place(x=350, y=640)
op_status_lable = tk.Label(control_frame, text="显示模式：", font=('SimSun', 20, 'bold'))
op_status_lable.place(x=100, y=654)

b_var = tk.IntVar()
b_button = tk.Button(control_frame, text="不启用", command=toggle_opc, font=button_font, width=8)
b_button.place(x=350, y=805)
b_lable = tk.Label(control_frame, text="邻近效应修正(OPC)：", font=('SimSun', 20, 'bold'))
b_lable.place(x=50, y=821)


# 添加帮助按钮
help_button = tk.Button(root, text="帮助/Help", command=show_help, font=button_font, width=10)
help_button.place(x=1750, y=10, anchor='ne')

# 署名
ln_font = ('KaiTi', 20)
ln1=tk.Label(control_frame,text="by 郭新会 霍晋元 吴昱璋 杨远青", font=ln_font)
ln1.place(x=80,y=980)
ln2=tk.Label(control_frame,text="复旦大学 物理学系22级", font=ln_font)
ln2.place(x=150,y=1030)


# 装置示意图初始化绘制
draw_static_elements(device_canvas)
draw_dynamic_elements(device_canvas, 10/(0.99**0.5), 1.0)


# 设置滑块的默认值
default_sin_val = 0.9
default_n_val = 1.4
default_wavelength_val = 2.0
default_m_val = 0
default_b_val = 0
default_op_status_val = 0

sin_slider.set(default_sin_val)
n_slider.set(default_n_val)
wavelength_slider.set(default_wavelength_val)
m_var.set(default_m_val)
b_var.set(default_b_val)
op_status_var.set(default_op_status_val)


# 初始化时先执行一次更新fig图像
update_mask()
update_result()


root.protocol("WM_DELETE_WINDOW", on_closing)

root.mainloop()

